﻿/* $Author: alexander@bsrgin.ru $
 * $Id: AlarmClockView.java 17 2011-11-17 21:38:48Z alexander@bsrgin.ru $
 * 
 * Описание view с часами, с автоматическим масштабированием содержимого.
 */
package ru.habrahabr.prettyalarm;

import java.text.SimpleDateFormat;
import java.util.Date;

import android.content.Context;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
import android.widget.TextView;

/**
 * View с часами, с автоматическим масштабированием содержимого (по высоте).
 * View выполняет запуск собственного потока для перерисовки текущего времени.
 * @author basargin
 */
public class AlarmClockView extends ViewGroup
{
	private volatile Handler handler = null;
	private volatile Thread thread = null;
	private int thread_tick;
	
	private TextView tvSeparator;
	private TextView tvHour;
	private TextView tvMinute;
	
	public AlarmClockView(Context context)
	{
		super(context, null);
		createTexts(context);
		startFlashing();
	}

	public AlarmClockView(Context context, AttributeSet attrs)
	{
		super(context, attrs);
		createTexts(context);
		startFlashing();
	}
	
	public AlarmClockView(Context context, AttributeSet attrs, int defStyle)
	{
		super(context, attrs, defStyle);
		createTexts(context);
		startFlashing();
	}

	/**
	 * Создание text views для отображения текущего времени.
	 * @param context контекст
	 */
	private void createTexts(Context context)
	{
		RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
				RelativeLayout.LayoutParams.WRAP_CONTENT,
				RelativeLayout.LayoutParams.WRAP_CONTENT);

		//tv.setTypeface(Typeface.createFromAsset(getContext().getAssets(),"Clockopia.ttf"));

		tvSeparator = new TextView(context);
		tvSeparator.setLayoutParams(lp);
		addView(tvSeparator);
		tvSeparator.setText(":");
		tvSeparator.setTextColor(0xffd22b21/*R.color.alarm_clock_time*/);
		tvSeparator.setVisibility(TextView.GONE);
		
		tvHour = new TextView(context);
		tvHour.setLayoutParams(lp);
		addView(tvHour);
		tvHour.setTextColor(0xffd22b21/*R.color.alarm_clock_time*/);
		
		tvMinute = new TextView(context);
		tvMinute.setLayoutParams(lp);
		addView(tvMinute);
		tvMinute.setTextColor(0xffd22b21/*R.color.alarm_clock_time*/);
	}

	@Override
	protected void onDetachedFromWindow()
	{
		stopFlashing();
		super.onDetachedFromWindow();
	}

	@Override
	protected void onLayout(boolean changed, int left, int top, int right, int bottom) 
	{
		int width = right - left + 1;
		int height = bottom - top + 1;
		
		adjustTextBounds(tvSeparator, 200, width, height);
		int seperator_width = tvSeparator.getMeasuredWidth();
		tvSeparator.layout(width/2-seperator_width/2-1, 0, width/2+seperator_width/2+1, height);
		tvSeparator.setGravity(Gravity.CENTER_VERTICAL);
		
		tvMinute.setTextSize(TypedValue.COMPLEX_UNIT_PX, tvSeparator.getTextSize());
		tvMinute.layout(tvSeparator.getRight(), 0, width, height);
		tvMinute.setGravity(Gravity.LEFT);
		
		tvHour.setTextSize(TypedValue.COMPLEX_UNIT_PX, tvSeparator.getTextSize());
		tvHour.layout(0, 0, tvSeparator.getLeft(), height);
		tvHour.setGravity(Gravity.RIGHT);
	}
	
	// см. http://www.pushing-pixels.org/2010/12/16/meet-the-green-goblin-part-4.html
	// см. http://android-argentina.blogspot.com/2011/01/resizablebutton.html
	/**
	 * Подгонка размера шрифта под размер выделенной для перерисовки области.
	 * @param tv text view, размер шрифта которого будет подобран
	 * @param max_text_size максимальный размер шрифта
	 * @param max_width ширина веделенной области
	 * @param max_height высота выделенной области
	 */
	private static void adjustTextBounds(TextView tv, float max_text_size, int max_width, int max_height)
	{
		int newWidth, newHeight;
		float size = max_text_size;
		do {
			tv.setTextSize(size--);
			tv.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
			newWidth = tv.getMeasuredWidth();
			newHeight = tv.getMeasuredHeight();
		} while (newWidth > max_width || newHeight > max_height);
	}
	
	/**
	 * Запуск потока, выполняющего обновление содержимого таймера времени.
	 */
	private void startFlashing()
	{
		handler = new Handler();
		thread = null;
		thread_tick = -1;
		thread = new Thread() {
			public void run() {
				final SimpleDateFormat hh = new SimpleDateFormat("HH");
				final SimpleDateFormat mm = new SimpleDateFormat("mm");
				while (Thread.currentThread() == thread) {
					try {
						if (handler != null)
							handler.post(new Runnable() {
								public void run() {
									if (tvSeparator == null) return;
									if ((++thread_tick)%60 == 0)
									{
										final Date now = new Date();
										tvHour.setText(hh.format(now));
										tvMinute.setText(mm.format(now));
									}
									if (tvSeparator.getVisibility() != TextView.GONE)
										tvSeparator.setVisibility(TextView.GONE);
									else
										tvSeparator.setVisibility(TextView.VISIBLE);
								}
							});
						Thread.sleep(1000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		};
		thread.start();
	}
	
	/**
	 * Останов потока, выполняющего обновление содержимого таймера времени.
	 */
	private void stopFlashing()
	{
		Thread moribund = thread;
		thread = null;
		moribund.interrupt();
		handler = null;
	}
}
